
#ifndef NATIVE_CAMERA_DEMO_AVPLAYER_H
#define NATIVE_CAMERA_DEMO_AVPLAYER_H

#include <cstdint>
#include <map>
#include "ace/xcomponent/native_interface_xcomponent.h"
#include "js_native_api.h"
#include "multimedia/player_framework/avplayer.h"
#include "napi/native_api.h"
#include "native_window/external_window.h"
#include <js_observer.h>

class AvPlayer final {
public:
    static AvPlayer &GetInstance()
    {
        static AvPlayer instance;
        return instance;
    }
    void Export(napi_env env, napi_value exports);
    void Play(int32_t fd, int64_t size);
    void PlayCon();
    void Pause();
    void RegOnFinish(std::shared_ptr<JSObserver> observer);
    void RegDuration(std::shared_ptr<JSObserver> observer);
    void RegPos(std::shared_ptr<JSObserver> observer);

private:
    struct PlayerPara {
        AVPlayerBufferingType bufferType = AVPLAYER_BUFFERING_START;
        AVPlayerState avState = AV_IDLE;
        AVPlaybackSpeed speed = AV_SPEED_FORWARD_1_00_X;

        OH_AVPlayer *player = nullptr;
        int32_t errorCode = AV_ERR_UNKNOWN;
        int32_t value = -1;
        int32_t state = -1;
        int32_t stateChangeReason = -1;

        float volume = 0.0;
        int64_t duration = -1;
    
        int32_t width = -1;
        int32_t height = -1;
        int32_t bufferValue = -1;
    
        size_t bitRatesSize = 0;
        uint32_t *bitRates = nullptr;
        uint32_t bitRate = 0;
    
        int32_t interruptType = -1;
        int32_t interruptForce = -1;
        int32_t interruptHint = -1;
    };

    static void OnSurfaceCreated(OH_NativeXComponent *component, void *window);
    static void OnSurfaceDestroyed(OH_NativeXComponent *component, void *window);
    static void HandleStateChange(OH_AVPlayer *player, AVPlayerState state);
    static void OnInfoCallback(OH_AVPlayer *player, AVPlayerOnInfoType type, OH_AVFormat *infoBody, void *userData);
    static void OnErrorCallback(OH_AVPlayer *player, int32_t errorCode, const char *errorMsg, void *userData);
    static void BitrateCollect(OH_AVFormat *infoBody, PlayerPara *playerPara);

    static std::map<AVPlayerOnInfoType, std::function<void(OH_AVPlayer *, OH_AVFormat *, PlayerPara *)>> stateChange_;
    static OHNativeWindow *nativeWin_;
    OH_NativeXComponent_Callback callback_;
    PlayerPara *para_ = nullptr;
    static std::shared_ptr<JSObserver> observer_;
    static std::shared_ptr<JSObserver> durationObserver_;
    static std::shared_ptr<JSObserver> posObserver_;
};

#endif //NATIVE_CAMERA_DEMO_AVPLAYER_H